package com.zz.framework.core.http

import com.zz.framework.BuildConfig
import com.zz.framework.core.ext.toLanguage
import com.zz.framework.core.utils.LogUtils
import com.zz.framework.core.utils.language.Strings
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlin.coroutines.cancellation.CancellationException

/**
 * Copyright © 2024 zhun All rights reserved.
 * Created by Zha0Zhun on 2024/6/30 23:13.
 * @author: Zha0Zhun 1820022519@qq.com
 * @version: V1.0
 */
abstract class BaseRepository {
    suspend fun <T> makeApiCall(
        dispatcher: CoroutineDispatcher = Dispatchers.IO,
        call: suspend () -> IResponse<T>,
    ): Result<T?> = runCatching {
        withContext(dispatcher) {
            call.invoke()
        }
    }.recoverCatching {
        if (it is CancellationException){
            throw CancelException("")
        }
        if (BuildConfig.DEBUG) {
            throw ServerException(500, it.message)
        } else {
            throw ServerException(500, Strings.请求失败请稍后重试.toLanguage())
        }
    }.mapCatching { response ->
        if (response.isSuccess()) {
            response.data()
        } else if(response.code()==3){//登录失效
            throw ApiException(response.code(), response.message())
        } else {
            throw ApiException(response.code(), response.message())
        }
    }.onFailure { throwable ->
        when (throwable) {
            is ApiException -> {
                // 处理ApiException，接口异常
                LogUtils.error("错误消息：${throwable.message} 错误编码：${throwable.code}")
            }
            is ServerException -> {
                // 处理ApiException，比如记录日志
                LogUtils.error("服务器错误消息：${throwable.message} 错误编码：${throwable.code}")
            }
            is CancelException -> {
                LogUtils.error("请求取消消息：${throwable.message}")
            }
            else -> {
                // 处理其他异常
                LogUtils.error("未知错误：${throwable.localizedMessage}")
            }
        }
    }

    suspend fun <T> callApi(
        dispatcher: CoroutineDispatcher = Dispatchers.IO,
        call: suspend () -> T,
    ): Result<T?> = runCatching {
        withContext(dispatcher) {
            call.invoke()
        }
    }

    inline fun <reified T : Any> createInstance(): T {
        return T::class.java.getDeclaredConstructor().newInstance()
    }

    //创建实例
    inline fun <reified T : Any> createDefaultInstance(): T? {
        return try {
            T::class.java.getDeclaredConstructor().newInstance()
        } catch (e: Exception) {
            null
        }
    }

}

class ApiException(val code: Int, override val message: String?) : Exception(message)
class ServerException(val code: Int, override val message: String?) : Exception(message)
class CancelException(override val message: String?) : Exception(message)

